home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / GAMES / WIMP / MINES2 / !Mines / c / Mines < prev    next >
Text File  |  1995-05-01  |  28KB  |  847 lines

  1. /* Mines
  2.    Diese wunderbare Version wurde geschrieben von:
  3.      Michael Dreyer
  4.      Tycho-Brahe-Weg 44b
  5.      22043 Hamburg
  6.      Germany
  7.      Email: dreyer@physnet.uni-hamburg.de
  8.  
  9.    Have much fun !        */
  10.  
  11. /* Einige lustige includes ... */
  12. #include "wimp.h"        /*  access to WIMP SWIs                      */
  13. #include "colourtran.h"  /*  interface to colour translation module   */
  14. #include "os.h"          /*  low-level RISCOS access                  */
  15. #include "alarm.h"
  16. #include "mouse.h"
  17. #include "osspriteop.h"
  18. #include "osword.h"
  19.  
  20. /* ... und noch ein paar ... */
  21. #include <string.h>
  22. #include <limits.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25.  
  26. #define VERSION "2.00 31.4.1995" /* Momentane Versionsnummer (Wird ständig geändert) */
  27.  
  28. #define INFO 0
  29. #define LEV1 1
  30. #define LEV2 2
  31. #define LEV3 3
  32. #define LEV4 4
  33. #define CUSTOM 5
  34. #define HINT 6
  35. #define NEU 7
  36. #define QUIT 8
  37.  
  38. #define MINE 1      /* Flags für die Felder */
  39. #define MARK 2
  40. #define CLOSED 4
  41.  
  42. /* einige nützliche Definitionen */
  43. #define SpriteSize   2000+X_SIZE*Y_SIZE/2+sizeof(osspriteop_header)+sizeof(osspriteop_area)
  44. #define MODE         12
  45. #define X_SIZE       610
  46. #define Y_SIZE       192
  47.  
  48. #define TickMenu(m,n) (m.entries[n].menu_flags |= wimp_MENU_TICKED)
  49. #define UntickMenu(m,n) (m.entries[n].menu_flags &= ~wimp_MENU_TICKED)
  50. #define ToggleTickMenu(m,n) (m.entries[n].menu_flags ^= wimp_MENU_TICKED)
  51.  
  52. #define ShadeMenu(m,n) (m.entries[n].icon_flags |= wimp_ICON_SHADED)
  53. #define UnshadeMenu(m,n) (m.entries[n].icon_flags &= ~wimp_ICON_SHADED)
  54. #define ToggleShadeMenu(m,n) (m.entries[n].icon_flags ^= wimp_ICON_SHADED)
  55.  
  56. typedef struct
  57.         { osspriteop_area *area;
  58.           osspriteop_id   id;
  59.         } spr_details;
  60.  
  61. typedef struct {wimp_w w ;
  62.                 wimp_window *window ;
  63.                 char *font ;
  64.                 char *buffer ;
  65.                }window_data ;
  66.  
  67. typedef int BOOL ;
  68.  
  69. #define HEIGHT 192 /* wird möglicherweise mal variabel */
  70. #define WEIDTH 610
  71. #define XOFF 5
  72. #define YOFF 3
  73. #define XMAX 30
  74. #define YMAX 16
  75.  
  76. /* My Icon Flags */
  77. #define MIF (wimp_ICON_TEXT|wimp_ICON_VCENTRED|(7<<wimp_ICON_FG_COLOUR_SHIFT))
  78.  
  79. #include "Hint.h"
  80.  
  81. static window_data mainwindow = {0,0,0,0} ;       /* DAS Spielfenster */
  82. static window_data winwindow = {0,0,0,0};   /* Das Fenster zum Gewinnen */
  83. static window_data infowindow = {0,0,0,0};
  84. static wimp_MENU(3) cusmenu = {{'M','i','n','e','s',0,0,0,0,0,0,0},
  85.                                  7,2,7,0,150,36,4,
  86.                                  {{wimp_MENU_WRITABLE|wimp_MENU_LAST,(wimp_menu*)-1,
  87.                                    wimp_ICON_INDIRECTED|MIF,{0,0,0,0,0,0,0,0,0,0,0,0}}}} ;
  88. /* das Hauptmenu */
  89. static wimp_MENU(9) mainmenu = {{'M','i','n','e',' ','M','e','n','u',0,0,0},
  90.                                     7,2,7,0,150,36,4,
  91.                                     {{wimp_MENU_SEPARATE,(wimp_menu*)-1,MIF,
  92.                                       {'I','n','f','o',0,0,0,0,0,0,0,0}},
  93.                                      {0,(wimp_menu*)-1,MIF,
  94.                                        {'B','e','g','i','n','n','e','r',0,0,0,0}},
  95.                                      {0,(wimp_menu*)-1,MIF,
  96.                                        {'N','o','v','i','c','e',0,0,0,0,0,0}},
  97.                                      {0,(wimp_menu*)-1,MIF,
  98.                                        {'E','x','p','e','r','t',0,0,0,0,0,0}},
  99.                                      {0,(wimp_menu*)-1,MIF,
  100.                                        {'M','a','s','t','e','r',0,0,0,0,0,0}},
  101.                                      {wimp_MENU_SEPARATE,(wimp_menu*)&cusmenu,MIF,
  102.                                        {'C','u','s','t','o','m',0,0,0,0,0,0}},
  103.                                      {0,(wimp_menu*)-1,MIF,
  104.                                        {'H','i','n','t',0,0,0,0,0,0,0,0}},
  105.                                      {wimp_MENU_SEPARATE,(wimp_menu*)-1,MIF,
  106.                                        {'N','e','w',' ','G','a','m','e',0,0,0,0}},
  107.                                      {wimp_MENU_LAST,(wimp_menu*)-1,MIF,
  108.                                        {'Q','u','i','t',0,0,0,0,0,0,0,0}}}
  109.                                    } ;
  110. static spr_details my_sprite ;    /* Fenster Sprite */
  111. static spr_details open[9] ;      /* Zahlen auf dem Spielfeld */
  112. static char *openstr[9] = {"0","1","2","3","4","5","6","7","8"} ;
  113. static spr_details playground ;   /* Spielfeld */
  114. int feld[XMAX][YMAX] ;     /* DAS Spielfeld */
  115. spr_details mark ;         /* Markiertes Feld */
  116. spr_details cover;         /* Normal Bedecktes Feld */
  117. spr_details mine ;         /* Mine */
  118. spr_details nomine ;       /* doch keine Mine */
  119. spr_details questionmark;  /* ein Fragezeichen */
  120. spr_details barsprite ;
  121. static spr_details number[11] ;   /* Zahlen zur Anzeige */
  122. static char *numberstr[11] = {"nleer","n0","n1","n2","n3","n4","n5","n6","n7","n8","n9"} ;
  123. static BOOL displaying = FALSE;    /* window on display?           */
  124. /* =-1 : Game Over
  125.   sonst Bit 0 : player 0,1
  126.             1 : =1 : Droping
  127. */
  128. int mines_left = -1,fields_left = 0; /* Zähler Variable */
  129. /* Richtungen zum Suchen */
  130. int off[8][2] = { {-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}};
  131. static int level = 0,anzahl[4] = {30,60,90,120} ; /* Level Daten */
  132. static osspriteop_trans_tab *trans; /* colour translation table */
  133. static char cusstr[4] ; /* Speicher fuer das Custom Menu */
  134. static wimp_t I_am ;
  135. static int This_Version ;
  136. static wimp_i baricon ;
  137.  
  138. void res_feld(void) ;               /* alle Header */
  139. void redraw_window(wimp_w handle) ;
  140. void update_window(wimp_draw r) ;
  141. void redo_window(wimp_draw r, BOOL more) ;
  142. void open_window(wimp_open *o);
  143. void icon_links(void) ;
  144. void mine_handler(void) ;
  145. void create_sprite(void);
  146. static BOOL main_init(void);
  147. void res_sprite(void);
  148. void click_on(int x,int y, bits button ) ;
  149. void open_field(int x,int y) ;
  150. void show_all(void) ;
  151. int count(int x,int y) ;
  152. int tidy_up(int x,int y) ;
  153. int no_error(void);
  154. void win(void) ;
  155. void close_win_window(void);
  156. void show_anzahl(void) ;
  157. void blotch(void);
  158.  
  159. void werr(os_error *err)
  160. {if(err != 0)
  161.    {wimp_report_error(err,2,"!Test") ;
  162.     exit(1) ;
  163.    }
  164. }
  165.  
  166. void loosewin(window_data *w)
  167. {int i,j,h ;
  168.  if(w->w != 0)
  169.    {while((j=w->font[i++])>0)
  170.       {h = w->font[i++] ;
  171.        while(h-->0)
  172.          werr(xfont_lose_font(j)) ;
  173.       }
  174.      free(w->buffer) ;
  175.      free(w->font) ;
  176.      free(w->window) ;
  177.      w->w = 0 ;
  178.    }
  179. }
  180.  
  181. void loadwin(window_data *w,char *s)
  182. {char win[13] ;
  183.  int i,j,k ;
  184.  font_f font[256] ;
  185.  strncpy(win,s,12);
  186.  win[13] = 0 ;
  187.  werr(xwimp_load_template(0,0,0,font,win,0,&i,&j,&k)) ;
  188.  w->window = (wimp_window*)malloc(i+j) ;
  189.  if( j>0) w->buffer = malloc(j) ;
  190.  else w->buffer = 0 ;
  191.  for(i=0;i<256;i++) font[i]=0;
  192.  werr(xwimp_load_template(w->window,w->buffer,w->buffer+j,font,win,0,&i,&j,&k));
  193.  j = 0 ;
  194.  for(i=0;i<256;i++) if(font[i]) j++ ;
  195.  w->font = (char*) malloc(j*2+2) ;
  196.  j = 0 ;
  197.  for(i=0;i<256;i++) if(font[i]) {w->font[j++] = i ; w->font[j++] = font[i];}
  198.  w->font[j++] = 0 ;
  199.  w->font[j++] = 0 ;
  200. }
  201.  
  202. /* Feder initialisieren (feld,bottom,vlines,lines)*/
  203. void res_feld()
  204. {int i,j ;
  205.  div_t r ;
  206.  if(level == 4) /* Zahl der Minen suchen */
  207.    {sscanf(cusstr,"%d",&mines_left) ;
  208.     if(mines_left < 30) mines_left = 30 ;  /* Minimum */
  209.     if(mines_left > XMAX*YMAX*90/100) mines_left = XMAX*YMAX*90/100; /* Maximum 90% */
  210.    }
  211.  else
  212.    mines_left = anzahl[level] ;
  213.  sprintf(cusstr,"%d",mines_left) ;/* Minenzahl ins Custom-Menu */
  214.  fields_left = XMAX*YMAX-mines_left ;/* Freie Felder */
  215.  for( i = 0 ; i < XMAX ; i++ ) /* alle Felder ohne Mienen und geschlossen */
  216.     for( j = 0 ; j < YMAX ; j++ )
  217.        feld[ i ][ j ] = CLOSED ;
  218.  for( i=0 ; i<mines_left ;i++) /* jetzt ein paar Minen legen */
  219.     {do{r = div( rand() , XMAX ) ;
  220.         j = r.rem ;
  221.         r = div( rand() , YMAX ) ;
  222.        }while(feld[j][r.rem] & MINE) ;
  223.      feld[j][r.rem] |= MINE ;
  224.     }
  225. }
  226.  
  227. /* Sprite zurücksetzen */
  228. void res_sprite(void)
  229. {osspriteop_save_area *old;
  230.  int i,j,s1,s2,s3,s4;
  231.  /* alles in mein Sprite */
  232.  old = (osspriteop_save_area *)malloc(osspriteop_read_save_area_size(osspriteop_PTR,my_sprite.area,my_sprite.id)) ;
  233.  old->a[0] = 0 ;
  234.  werr(xosspriteop_switch_output_to_sprite(osspriteop_PTR,my_sprite.area,my_sprite.id,old,&s1,&s2,&s3,&s4));
  235.  /* Feld plotten */
  236.  osspriteop_put_sprite_user_coords(osspriteop_PTR,playground.area,playground.id,0,0,0);
  237.  for(i=0 ; i<XMAX ; i++)
  238.     for(j=0 ; j<YMAX ; j++)
  239.         osspriteop_put_sprite_user_coords(osspriteop_PTR,cover.area,cover.id,(XOFF+i*20)*2,(YOFF+j*10)*4,0);
  240.  /* ab hier wieder normal */
  241.  werr(xosspriteop_unswitch_output(s1,s2,s3,s4)) ;
  242.  free(old) ;
  243. }
  244.  
  245. void draw_sprite(int x,int y,osspriteop_id help)
  246. {wimp_draw r;
  247.  osspriteop_save_area *old;
  248.  int s1,s2,s3,s4;
  249.  old = (osspriteop_save_area *)malloc(osspriteop_read_save_area_size(osspriteop_PTR,my_sprite.area,my_sprite.id)) ;
  250.  old->a[0] = 0 ;
  251.  werr(xosspriteop_switch_output_to_sprite(osspriteop_PTR,my_sprite.area,my_sprite.id,old,&s1,&s2,&s3,&s4));
  252.  osspriteop_put_sprite_user_coords(osspriteop_PTR,cover.area,help,(XOFF+x*20)*2,(YOFF+y*10)*4,0);
  253.  werr(xosspriteop_unswitch_output(s1,s2,s3,s4)) ;
  254.  r.w = mainwindow.w ;
  255.  r.box.x0 = (x*20+XOFF)*2 ;
  256.  r.box.y0 = (10*y+YOFF-HEIGHT)*4 ;
  257.  r.box.x1 = ((x+1)*20+XOFF)*2 ;
  258.  r.box.y1 = (10*(y+1)-HEIGHT+YOFF)*4 ;
  259.  update_window(r) ;
  260.  free(old) ;
  261. }
  262.  
  263. /* Mouse-Click verarbeiten */
  264. void click_on(int x,int y,bits button)
  265. {wimp_window_state wstate ;
  266.  osspriteop_id help ;
  267.  int x1,y1 ;
  268.  wstate.w = mainwindow.w ;
  269.  wimp_get_window_state(&wstate) ;  /*Koordinatentransformation*/
  270.  x1 = (x+wstate.xscroll-wstate.visible.x0-XOFF*2)/2/20 ;
  271.  y1 = (y+wstate.yscroll-wstate.visible.y0-YOFF*4)/4/10 ;
  272.  if(x1>=0 && x1<XMAX && y1>=0 && y1<YMAX && mines_left != -1) /* Innerhalb und erlaubt ?*/
  273.    { hint_choose_done(x1,y1,&button);
  274.      if( (button == wimp_CLICK_SELECT) && !(feld[x1][y1] & MARK) )    /* Ausknobeln was getan werden soll*/
  275.       {if(feld[x1][y1] & MINE)  /* Links auf geschlossene Mine ? */
  276.          show_all() ;           /* ja : leider verloren */
  277.        else if(feld[x1][y1] & CLOSED)
  278.          {open_field(x1,y1) ;   /* sonst öffnen */
  279.           if(fields_left == 0)  /* alle freien Felder gefunden ? */
  280.             win() ;             /* dann war das der Sieg */
  281.          }
  282.       }
  283.     else if (button == wimp_CLICK_ADJUST)  /* Rechte Taste */
  284.       {if( (feld[x1][y1] & CLOSED) && ( (mines_left > 0) || ((feld[x1][y1] & MARK) )) && (mines_left != -1))
  285.          {feld[x1][y1] ^= MARK ;  /* Marke toggeln */
  286.           if(feld[x1][y1] & MARK)
  287.             {help = mark.id ;
  288.              mines_left-- ;
  289.              show_anzahl() ;
  290.              if ((mines_left==0) && no_error()) win();
  291.             }
  292.           else
  293.             {help = cover.id ;
  294.              mines_left++ ;
  295.              show_anzahl() ;
  296.             }
  297.           draw_sprite(x1,y1,help);
  298.          }
  299.        else
  300.          {if( !(feld[x1][y1] & CLOSED) )
  301.             {if(tidy_up(x1,y1))
  302.                show_all() ;
  303.             else
  304.               {if ((fields_left == 0) && no_error()) win();
  305.               }
  306.             }
  307.          }
  308.       }
  309.    }
  310. }
  311.  
  312. int no_error(void)
  313. {
  314.   int x,y;
  315.   for (x=0;x<XMAX;x++) for (y=0;y<YMAX;y++)
  316.     if (((feld[x][y] & MINE) && !(feld[x][y] & MARK)) ||
  317.         (!(feld[x][y] & MINE) && (feld[x][y] & MARK))) return FALSE;
  318.   return TRUE;
  319. }
  320.  
  321. extern int unnecessary_hints;
  322. /* eine sehr einfache Siegesroutiene */
  323. void win(void)
  324. {
  325.   wimp_window_state s;
  326.   wimp_icon *i=winwindow.window->icons ;
  327.   show_all();
  328.   sprintf(i[0].data.indirected_text.text,"Unnecessary hints : %3i",unnecessary_hints);
  329.   s.w = winwindow.w ;
  330.   wimp_get_window_state(&s);
  331.   s.next=wimp_TOP;
  332.   wimp_open_window((wimp_open*)&s);
  333. }
  334.  
  335. /* aufräumen (Rechtsclick auf ein offenes Feld */
  336. int tidy_up(int x,int y)
  337. {int c = count(x,y) ;
  338.  int i,x1,y1 ;
  339.  for(i=0 ; i<8 ; i++)
  340.     {x1 = x+off[i][0] ;
  341.      y1 = y+off[i][1] ;
  342.      if(x1>=0 && x1<XMAX && y1>=0 && y1<YMAX)
  343.        if(feld[x1][y1] & MARK)
  344.          c-- ;
  345.     }
  346.  if(c==0)
  347.    {for(i=0 ; i<8 ; i++)
  348.       {x1 = x+off[i][0] ;
  349.        y1 = y+off[i][1] ;
  350.        if(x1>=0 && x1<XMAX && y1>=0 && y1<YMAX)
  351.          {if( feld[x1][y1] & CLOSED )
  352.             {if( !(feld[x1][y1] & MARK) )
  353.                {if( feld[x1][y1] & MINE)
  354.                   return 1 ;
  355.                 else
  356.                   open_field(x1,y1) ;
  357.                }
  358.             }
  359.          }
  360.       }
  361.    }
  362.  return 0 ;
  363. }
  364.  
  365. /* Ein Feld (gegebenenfalls mehrere rekursiv) oeffnen */
  366. void open_field(int x,int y)
  367. {int i ;
  368.  osspriteop_id help ;
  369.  if(x>=0 && x<XMAX && y>=0 && y<YMAX)
  370.    {help = open[i=count(x,y)].id ;
  371.     feld[x][y] &= ~CLOSED ;
  372.     fields_left-- ;
  373.     draw_sprite(x,y,help);
  374.     if(i == 0)
  375.       {for(i=0;i<8;i++)
  376.          if( (feld[x+off[i][0]][y+off[i][1]] & CLOSED)
  377.              && !(feld[x+off[i][0]][y+off[i][1]] & MARK))
  378.             open_field(x+off[i][0],y+off[i][1]) ;
  379.       }
  380.    }
  381. }
  382.  
  383. /* alles zeigen */
  384. void show_all(void)
  385. {int x,y,h,s1,s2,s3,s4 ;
  386.  wimp_draw r;
  387.  osspriteop_save_area *old ;
  388.  osspriteop_id help ;
  389.  mines_left = -1 ;
  390.  ShadeMenu(mainmenu,HINT) ;
  391.  old = (osspriteop_save_area *)malloc(osspriteop_read_save_area_size(osspriteop_PTR,my_sprite.area,my_sprite.id)) ;
  392.  old->a[0] = 0 ;
  393.  for(x=0 ; x<XMAX ; x++)
  394.   {werr(xosspriteop_switch_output_to_sprite(osspriteop_PTR,my_sprite.area,my_sprite.id,old,&s1,&s2,&s3,&s4));
  395.    for(y=0 ; y<YMAX ; y++)
  396.      {h = feld[x][y] ;
  397.       help = 0 ;
  398.       if(h & MINE)
  399.         {if( !(h & MARK) )
  400.            help = mine.id ;
  401.         }
  402.       else
  403.         {if( h & CLOSED )
  404.            {if(h & MARK)
  405.               help = nomine.id ;
  406.             else
  407.               help = open[count(x,y)].id ;
  408.            }
  409.         }
  410.       if(help)
  411.         osspriteop_put_sprite_user_coords(osspriteop_PTR,my_sprite.area,help,(XOFF+x*20)*2,(YOFF+y*10)*4,0);
  412.      }
  413.    werr(xosspriteop_unswitch_output(s1,s2,s3,s4)) ;
  414.    r.w = mainwindow.w ;
  415.    r.box.x0 = (x*20+XOFF)*2 ;
  416.    r.box.y0 = (-HEIGHT+YOFF)*4 ;
  417.    r.box.x1 = ((x+1)*20+XOFF)*2 ;
  418.    r.box.y1 = (10*YMAX-HEIGHT+YOFF)*4 ;
  419.    update_window(r) ;
  420.   }
  421.  show_anzahl() ;
  422.  free(old) ;
  423. }
  424.  
  425. void blotch(void)
  426. {int x,y,min,x1,y1;
  427.  int i,j,k,l,h ;
  428.  x = XMAX/2 ;
  429.  y = YMAX/2 ;
  430.  min = 9 ;
  431.  if(XMAX>YMAX)
  432.    j = x ;
  433.  else
  434.    j = y ;
  435.  if(x>=0 && x<XMAX && y>=0 && y<YMAX)
  436.    {if( !(feld[x][y] & MINE) && (feld[x][y] & CLOSED) )
  437.       {x1 = x ;
  438.        y1 = y ;
  439.        min = count(x,y) ;
  440.       }
  441.    }
  442.  x-- ;
  443.  y-- ;
  444.  for(i=1;i<=j;i++)
  445.    {for(l=0 ; l<4 ; l++)
  446.       {k = 2 * i + 1 ;
  447.        do{if(x>=0 && x<XMAX && y>=0 && y<YMAX)
  448.             {if( !(feld[x][y] & MINE) && (feld[x][y] & CLOSED) )
  449.                {h = count(x,y) ;
  450.                 if(h<min)
  451.                   {x1 = x ;
  452.                    y1 = y ;
  453.                    min = h ;
  454.                   }
  455.                }
  456.             }
  457.           k-- ;
  458.           if(k>0)
  459.             {switch(l)
  460.                {case 0:
  461.                   x++ ;
  462.                   break ;
  463.                 case 1:
  464.                   y++ ;
  465.                   break ;
  466.                 case 2:
  467.                   x-- ;
  468.                   break ;
  469.                 case 3:
  470.                   y-- ;
  471.                   break ;
  472.                }
  473.             }
  474.          }while(k>0) ;
  475.       }
  476.     x-- ;
  477.     y-- ;
  478.    }
  479.  if(min!=9) open_field(x1,y1) ;
  480. }
  481.  
  482. /* Anzahl der Minen minus Anzahl der Markierungen anzeigen */
  483. void show_anzahl(void)
  484. {int flag = 0,h2 = mines_left,h1 = 1000,h3,i,s1,s2,s3,s4 ;
  485.  osspriteop_save_area *old ;
  486.  osspriteop_id shelp ;
  487.  wimp_draw r;
  488.  if(h2<0) h2 = 0 ;
  489.  old = (osspriteop_save_area *)malloc(osspriteop_read_save_area_size(osspriteop_PTR,my_sprite.area,my_sprite.id)) ;
  490.  old->a[0] = 0 ;
  491.  osspriteop_switch_output_to_sprite(osspriteop_PTR,my_sprite.area,my_sprite.id,old,&s1,&s2,&s3,&s4);
  492.  for(i=0;i<4;i++)
  493.    {h3 = h2/h1 ;
  494.     if(h3 == 0)
  495.       {if((flag == 1) || (i == 3) )
  496.          shelp = number[1].id ;
  497.        else
  498.          shelp = number[0].id ;
  499.       }
  500.     else
  501.       {shelp = number[h3+1].id ;
  502.        flag = 1 ;
  503.       }
  504.     osspriteop_put_sprite_user_coords(osspriteop_PTR,my_sprite.area,shelp,(110+i*10)*2,(HEIGHT-10-9)*4,0);
  505.     h2 -= h1*h3 ;
  506.     h1 /= 10 ;
  507.    }
  508.  osspriteop_unswitch_output(s1,s2,s3,s4) ;
  509.  r.w = mainwindow.w ;
  510.  r.box.x0 = 110*2 ;
  511.  r.box.y0 = ((HEIGHT-10-9)-HEIGHT)*4 ;
  512.  r.box.x1 = (110+4*10)*2 ;
  513.  r.box.y1 = ((HEIGHT-8)-HEIGHT)*4 ;
  514.  update_window(r) ;
  515.  free(old) ;
  516. }
  517.  
  518. /* Anzahl der Minen um ein Feld zählen */
  519. int count(int x,int y)
  520. {int i,c=0,x1,y1 ;
  521.  for(i=0 ; i<8 ; i++)
  522.     {x1 = x+off[i][0] ;
  523.      y1 = y+off[i][1] ;
  524.      if(x1>=0 && x1<XMAX && y1>=0 && y1<YMAX)
  525.        if(feld[x1][y1] & MINE)
  526.          c++ ;
  527.     }
  528.  return c ;
  529. }
  530.  
  531. /* Windows und Dialogboxen */
  532.  
  533. void update_window(wimp_draw r)
  534. { wimp_draw new_r = r;
  535.   bool more;
  536.   more = wimp_update_window(&new_r);
  537.   if(more)
  538.     redo_window(new_r,more);
  539. }
  540.  
  541. void redo_window(wimp_draw r, BOOL more)
  542. {bool more_to_do = more;
  543.  wimp_draw  new_r = r;
  544.  os_factors factors;
  545.   /* --- ask how the WIMP is going to scale our sprite --- */
  546.  wimp_read_pix_trans(osspriteop_PTR,my_sprite.area, my_sprite.id, &factors, trans);
  547.   /* --- refresh the window's contents --- */
  548.  while (more_to_do)
  549.   {osspriteop_put_sprite_scaled(osspriteop_PTR,my_sprite.area,my_sprite.id,r.box.x0,r.box.y0,0,&factors,trans);
  550.    more_to_do = wimp_get_rectangle(&new_r);
  551.   }
  552. }
  553.  
  554. void redraw_window(wimp_w handle)
  555. {BOOL  more;
  556.  wimp_draw r;
  557.  wimp_window_info winfo;
  558.  winfo.w = handle;
  559.  wimp_get_window_info(&winfo);
  560.  /* --- do the redraw --- */
  561.  r.w = handle;
  562.  more = wimp_redraw_window(&r);
  563.  if (more)
  564.    redo_window(r, more);
  565. }
  566.  
  567. void open_window(wimp_open *o)
  568. {static int old_x, old_y;
  569.  o->xscroll = 0;  /* --- force scroll offsets to 0, since the window always --- */
  570.  o->yscroll = 0;  /* --- represents the whole display                       --- */
  571.  wimp_open_window(o);
  572.  /* --- only do a redraw if the size of the window has changed --- */
  573.  if (old_x != (o->visible.x1 - o->visible.x0) || old_y != (o->visible.y1 - o->visible.y0))
  574.    {
  575.     redraw_window(o->w);
  576.     old_x = o->visible.x1 - o->visible.x0;
  577.     old_y = o->visible.y1 - o->visible.y0;
  578.    }
  579. }
  580.  
  581. void icon_links()
  582. {wimp_window_state state;
  583.  if(mines_left == -10000 )
  584.    {res_feld();
  585.     res_sprite() ;
  586.     UnshadeMenu(mainmenu,HINT) ;
  587.     show_anzahl() ;
  588.     blotch() ;
  589.    }
  590. /* --- open the window we created --- */
  591.  state.w = mainwindow.w ;
  592.  wimp_get_window_state(&state) ;
  593.  state.next = wimp_TOP;  /* make sure it is opened in front */
  594.  open_window((wimp_open*)&state);
  595.  displaying = TRUE;
  596. }
  597.  
  598. /* event handler */
  599. void new_game(void)
  600. { wimp_window_state state;
  601.   close_win_window();
  602.   res_feld() ;
  603.   res_sprite() ;
  604.   hint_new_game();
  605.   show_anzahl();
  606.   if(displaying) wimp_force_redraw(mainwindow.w,0,-HEIGHT*4,WEIDTH*2,0);
  607.   else
  608.     {state.w = mainwindow.w ;
  609.      wimp_get_window_state(&state) ;
  610.      state.next = wimp_TOP;  /* make sure it is opened in front */
  611.      open_window((wimp_open*)&state);
  612.      if(displaying == FALSE)
  613.        {wimp_force_redraw(mainwindow.w,0,-HEIGHT*4,WEIDTH*2,0);
  614.         displaying = TRUE;
  615.        }
  616.     }
  617.   blotch() ;
  618.   UnshadeMenu(mainmenu,HINT);
  619. }
  620.  
  621. void end_game(void)
  622. {
  623.   close_win_window();
  624.   hint_exit();
  625.   exit(0) ;
  626. }
  627.  
  628. /* ********************* Fenster action ********************* */
  629. #define PollMask wimp_MASK_NULL|wimp_MASK_LEAVING|wimp_MASK_ENTERING|wimp_MASK_LOSE|wimp_MASK_GAIN
  630.  
  631. void mine_handler()
  632. {wimp_message reply ;
  633.  wimp_pointer pointer,*ppoint ;
  634.  int event,pw = 0 ;
  635.  static int mx,my ;
  636.  wimp_block b ;
  637.  while(1)
  638.    {werr(xwimp_poll(PollMask,&b,&pw,&event)) ;
  639.     switch(event)
  640.     {case wimp_REDRAW_WINDOW_REQUEST:
  641.         if(b.redraw.w == mainwindow.w) redraw_window(b.redraw.w);
  642.         break;
  643.       case wimp_OPEN_WINDOW_REQUEST:
  644.         if(b.open.w == mainwindow.w) open_window(&b.open);
  645.         else wimp_open_window(&b.open);
  646.         break;
  647.       case wimp_CLOSE_WINDOW_REQUEST:
  648.         if(b.close.w == mainwindow.w)
  649.            {wimp_close_window(b.close.w);
  650.             displaying = FALSE;
  651.            }
  652.         else if(b.close.w == winwindow.w) wimp_close_window(b.close.w);
  653.         break;
  654.       case wimp_MOUSE_CLICK: /* mouse buttons */
  655.         if(b.pointer.buttons == wimp_CLICK_MENU)
  656.           {mx = b.pointer.pos.x-75 ;
  657.            if(b.pointer.w == wimp_ICON_BAR)
  658.               werr(xwimp_create_menu((wimp_menu*)&mainmenu,mx,my=528)) ;
  659.            else
  660.               werr(xwimp_create_menu((wimp_menu*)&mainmenu,mx,my=b.pointer.pos.y)) ;
  661.           }
  662.         else if(b.pointer.w == mainwindow.w ) /* mein Fenster ? */
  663.           {if(mines_left != -1 ) click_on(b.pointer.pos.x,b.pointer.pos.y,b.pointer.buttons) ;
  664.           }
  665.         else if(b.pointer.i == baricon) icon_links() ;
  666.         else if(b.pointer.w == winwindow.w)
  667.           {if(b.pointer.buttons & wimp_CLICK_MENU) wimp_close_window(winwindow.w);
  668.            else if (b.pointer.i==1)
  669.              {wimp_close_window(winwindow.w);
  670.               new_game();
  671.              }
  672.            else if (b.pointer.i==2)
  673.              {wimp_close_window(winwindow.w);
  674.               end_game();
  675.              }
  676.           }
  677.         else hint_click(&b) ;
  678.         break;
  679.       case wimp_MENU_SELECTION:
  680.         werr(xwimp_get_pointer_info(&pointer));
  681.         switch(b.selection.items[0])
  682.           {case LEV1 :
  683.            case LEV2 :
  684.            case LEV3 :
  685.            case LEV4 :
  686.              UntickMenu(mainmenu,level+LEV1);
  687.              level = b.selection.items[0] - LEV1 ;
  688.              TickMenu(mainmenu,level+LEV1) ;
  689.              break ;
  690.            case CUSTOM :
  691.              if(b.selection.items[1] == 1 )
  692.                {UntickMenu(mainmenu,level+LEV1) ;
  693.                 level = b.selection.items[0] - LEV1 ;
  694.                 TickMenu(mainmenu,level+LEV1) ;
  695.                }
  696.              break ;
  697.            case NEU :
  698.              new_game();
  699.              break ;
  700.            case HINT :
  701.              hint_it() ;
  702.              break ;
  703.            case QUIT :
  704.              end_game();
  705.              break ;
  706.           }
  707.         if(pointer.buttons == wimp_CLICK_ADJUST) 
  708.           werr(xwimp_create_menu((wimp_menu*)&mainmenu,mx,my)) ;
  709.         break;
  710.       case wimp_USER_MESSAGE:
  711.       case wimp_USER_MESSAGE_RECORDED:     /* check for broadcast */
  712.         switch(b.message.action)
  713.         { case message_QUIT:
  714.             exit(0) ;
  715.             break ;
  716.           case message_PALETTE_CHANGE:  /* einfach neue Pallette anpassen */
  717.             colourtrans_select_table((os_mode)MODE,0,(os_mode)-1,(os_palette *)-1,(osspriteop_trans_tab *)trans);
  718.             break;
  719.           case message_MODE_CHANGE:    /* auch bei Mode-change */
  720.             colourtrans_select_table((os_mode)MODE,0,(os_mode)-1,(os_palette *)-1,(osspriteop_trans_tab *)trans);
  721.             break;
  722.           case 0x502:                  /* Help Request */
  723.             reply.your_ref = b.message.my_ref;
  724.             reply.action = 0x503;
  725.             reply.size = 256;
  726.             ppoint = (wimp_pointer*)&(b.message.data.reserved[0]) ;
  727.             if(ppoint->w == mainwindow.w) /*ie. window*/
  728.               sprintf((char*)reply.data.reserved,
  729.                 "SELECT on covered field opens (what ever will happen)|MADJUST on covered field toggles mark|MADJUST on open field opens known surroundings");
  730.             else if ((ppoint->w == wimp_ICON_BAR) && (ppoint->i == baricon))
  731.               sprintf((char *)reply.data.reserved,"Click SELECT to start displaying the game !");
  732.             else 
  733.               sprintf((char*)reply.data.reserved,
  734.                 "Mines is a tiny little testing application.|MThe rules could be found in the !Help file");
  735.             wimp_send_message(wimp_USER_MESSAGE,&reply,b.message.sender);
  736.             break;
  737.           default:
  738.             break;
  739.       }
  740.       default:  /* we're not interested in any other events */
  741.         break;
  742.     }
  743.   }
  744. }
  745.  
  746. void close_win_window(void)
  747. {
  748.   wimp_window_state s;
  749.   s.w = winwindow.w ;
  750.   wimp_get_window_state(&s);
  751.   if (s.flags & wimp_WINDOW_OPEN) wimp_close_window(winwindow.w);
  752. }
  753.  
  754. /* alles instalieren */
  755. void create_sprite(void)
  756. {int i;
  757.  osspriteop_area *a;
  758.  FILE *f ;
  759.  os_error error1 = {0,"Fatal error - failed to allocate store for sprite"};
  760.  if((my_sprite.area = (osspriteop_area*)malloc(SpriteSize)) == 0) /*allocate our own sprite area to hold display */
  761.    {wimp_report_error(&error1,1,"Mines");
  762.     exit(1) ;
  763.    }
  764.  my_sprite.area->size = SpriteSize ;
  765.  my_sprite.area->first = 16 ;
  766.  osspriteop_clear_sprites(osspriteop_PTR,my_sprite.area);
  767.  osspriteop_create_sprite(osspriteop_NAME,my_sprite.area,"minedisplay",0,X_SIZE,Y_SIZE,(os_mode)MODE);
  768.  my_sprite.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,my_sprite.area,(osspriteop_id)"minedisplay");
  769.  f=fopen("<Mines$Dir>.Sprites","r") ;
  770.  fseek(f,0,SEEK_END) ;
  771.  i = (int)ftell(f) ;
  772.  a = (osspriteop_area*)malloc(i+4) ;
  773.  fseek(f,0,SEEK_SET) ;
  774.  fread(((char*)a)+4,1,i,f) ;
  775.  fclose(f) ;
  776.  a->size = i+4 ;
  777.  playground.area=mark.area=cover.area=mine.area=nomine.area=questionmark.area=barsprite.area=a ;
  778.  playground.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)"playground");
  779.  mark.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)"mark");
  780.  cover.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)"cover");
  781.  mine.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)"mine");
  782.  nomine.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)"nomine");
  783.  for(i=0 ; i<9 ; i++)
  784.     {open[i].area = a ;
  785.      open[i].id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)openstr[i]);
  786.     }
  787.  for(i=0 ; i<11 ; i++)
  788.     {number[i].area=a ;
  789.      number[i].id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)numberstr[i]);
  790.     }
  791.  questionmark.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)"questionmark");
  792.  barsprite.id = (osspriteop_id)osspriteop_select_sprite(osspriteop_NAME,a,(osspriteop_id)"barmines");
  793. }
  794.  
  795. BOOL main_init(void)
  796. {wimp_icon_create bari; 
  797.  osword_timer_block clock ;
  798.  wimp_MESSAGE_LIST(10) ml ;
  799.  ml.messages[0] = message_PALETTE_CHANGE ;
  800.  ml.messages[1] = message_MODE_CHANGE ;
  801.  ml.messages[2] = 0x502 ;
  802.  ml.messages[3] = 0 ;
  803.  I_am = wimp_initialise(310,"Mines",(wimp_message_list*)&ml,&This_Version) ;
  804.  create_sprite() ;             /* sprites erzeugen b.z.w suchen */
  805.  werr(xwimp_open_template("<Mines$Dir>.Templates"));     /* her mit den Templates !*/
  806.  trans = (osspriteop_trans_tab *)malloc(16) ;
  807.  loadwin(&mainwindow,"MainWindow") ;/* Mainwindow suchen */
  808.  werr(xwimp_create_window( mainwindow.window , &(mainwindow.w) )) ;/* Hauptfenster erzeugen */
  809.                                                                 /* und Fehler abfangen */
  810.  loadwin(&winwindow,"Win") ;
  811.  werr(xwimp_create_window( winwindow.window , &(winwindow.w) )) ;
  812.  loadwin(&infowindow,"ProgInfo") ;
  813.  strncpy(infowindow.window->icons[9].data.indirected_text.text,VERSION,infowindow.window->icons[4].data.indirected_text.size-1);
  814.  werr(xwimp_create_window(infowindow.window,&infowindow.w));
  815.  mainmenu.entries[0].sub_menu = (wimp_menu*)infowindow.w ;
  816.  if (!hint_init()) return FALSE;
  817.  cusmenu.entries[0].data.indirected_text.text = cusstr ;
  818.  cusmenu.entries[0].data.indirected_text.validation = "a0-9" ;
  819.  cusmenu.entries[0].data.indirected_text.size = 4 ;
  820.  baricon = 0 ;
  821.  bari.w = wimp_ICON_BAR_RIGHT ;
  822.  bari.icon.extent.x0 = 0 ;
  823.  bari.icon.extent.y0 = 0 ;
  824.  bari.icon.extent.x1 = 78 ;
  825.  bari.icon.extent.y1 = 68 ;
  826.  bari.icon.flags = 0x0000311a ;
  827.  bari.icon.data.indirected_sprite.id = barsprite.id ;
  828.  bari.icon.data.indirected_sprite.area = barsprite.area ;
  829.  bari.icon.data.indirected_sprite.size = 0 ;
  830.  werr(xwimp_create_icon(&bari,&baricon)) ; /* Icon auf die Bar */
  831.  TickMenu(mainmenu,LEV1) ;
  832.  ShadeMenu(mainmenu,HINT) ;
  833.  wimp_close_template();
  834.   /* --- read the palette --- */
  835.  werr(xcolourtrans_select_table((os_mode)MODE,0,(os_mode)-1,(os_palette *)-1,(osspriteop_trans_tab *)trans));
  836.  mines_left = -10000 ; /* Flag für erstes mal */
  837.  werr(xosword_read_system_clock(&clock));
  838.  srand(clock.b[0]|clock.b[1]<<8|clock.b[2]<<16|clock.b[3]<<24 | 1) ;
  839.  return TRUE ;  /* hat alles geklappt */
  840. }
  841.  
  842. /* Hauptprogramm */
  843. int main()
  844. {if(main_init()) mine_handler() ;
  845.  return 0 ;
  846. }
  847.